package com.njcb.ams.store.stable;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.njcb.ams.assembler.SysTradeConsoleConvertor;
import com.njcb.ams.repository.dao.SysTradeConsoleDAO;
import com.njcb.ams.repository.dao.SysTradeLogDAO;
import com.njcb.ams.repository.entity.SysTradeConsole;
import com.njcb.ams.factory.domain.AppContext;
import com.njcb.ams.store.page.Page;
import com.njcb.ams.store.page.PageHandle;
import com.njcb.ams.support.annotation.Trader;
import com.njcb.ams.support.trade.TradeService;
import com.njcb.ams.support.trade.bean.TradeServiceBean;
import com.njcb.ams.util.AmsUtils;

/**
 * 服务控制服务类
 * @author liuyanlong
 *
 */
@Service("tradeConsoleService")
public class TradeConsoleService {

	private static final Logger logger = LoggerFactory.getLogger(TradeConsoleService.class);

	//控制器持有集合
	static HashMap<String, StableControl> stableMap = new HashMap<String, StableControl>();

	@Autowired
	private SysTradeLogDAO tradeLogDAO;

	@Autowired
	private SysTradeConsoleDAO sysServerConsoleDAO;

	@Autowired
	private SysTradeConsoleConvertor sysTradeConsoleConvertor;
	
	public static TradeConsoleService getInstance() {
		return AppContext.getBean(TradeConsoleService.class);
	}

	/**
	 * 获取交易控制配置实体类
	 * @param anm
	 * @return
	 */
	public SysTradeConsole getConsole(Trader anm) {
		StableControl sc = stableMap.get(anm.tradeCode());
		return sc.getSysServerConsole();
	}
	
	/**
	 * 
	 * 方法功能描述：申请流量服务及并发令牌
	 * 
	 * @param anm
	 */
	public void tryAcquire(Trader anm) {
		StableControl sc = stableMap.get(anm.tradeCode());
		sc.tryAcquireRate();
		sc.tryAcquireConc();
	}

	/**
	 * 释放指定交易的并发令牌
	 * 
	 * @param anm
	 */
	public void releaseAcquire(Trader anm) {
		StableControl sc = stableMap.get(anm.tradeCode());
		sc.release();
	}

	/**
	 * 根据输入条件查询控制器信息
	 * @param inBean 查询条件
	 * @return 结果集
	 */
	public List<SysTradeConsole> getTradeConsoleInfo(SysTradeConsole inBean) {
		logger.debug("查询条件{}",inBean);
		List<SysTradeConsole> tradeList = new ArrayList<SysTradeConsole>();
		List<?> retList = tradeLogDAO.getTradeUseTime(inBean);
		for (Entry<String, StableControl> entry : stableMap.entrySet()) {
			StableControl stableControl = entry.getValue();
			SysTradeConsole tcb = stableControl.getSysServerConsole();
			tcb.setTimeSpeed(0);
			tcb.setTimeTakeNum(0);
			tcb.setTimeSuccRate(SysTradeConsoleConvertor.DECIMAL_FORMAT.format(new BigDecimal(100)));
			if (null != inBean && null != inBean.getTradeCode()) {
				if (tcb.getTradeCode().indexOf(inBean.getTradeCode()) < 0) {
					continue;
				}
			}
			if (null != inBean && null != inBean.getTradeName()) {
				if (tcb.getTradeName().indexOf(inBean.getTradeName()) < 0) {
					continue;
				}
			}
			for (int i = 0; i < retList.size(); i++) {
				@SuppressWarnings("unchecked")
				Map<String, Object> map = (Map<String, Object>) retList.get(i);
				String tradeCode = (String) map.get("trade_code");
				if (tradeCode.trim().equals(tcb.getTradeCode())) {
					BigDecimal useTime = new BigDecimal(map.get("use_time").toString());
					BigDecimal tradeSum = new BigDecimal(map.get("trade_sum").toString());
					BigDecimal tradeSucc = new BigDecimal( map.get("trade_succ").toString());

					tcb.setTimeSpeed(useTime.intValue());
					tcb.setTimeTakeNum(tradeSum.intValue());
					if (tradeSum.compareTo(new BigDecimal(0)) > 0) {
						BigDecimal timeSuccRate = tradeSucc.divide(tradeSum, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
						tcb.setTimeSuccRate(SysTradeConsoleConvertor.DECIMAL_FORMAT.format(timeSuccRate));
						if (timeSuccRate.compareTo(new BigDecimal(0)) <= 0) {
							tcb.setTimeSuccRate("0.00");
						}

					}

				}
			}
			tcb.setTimeCycle(null == inBean || null == inBean.getTimeCycle() ? 0 : inBean.getTimeCycle());
			tradeList.add(tcb);
		}

		Collections.sort(tradeList, new Comparator<SysTradeConsole>() {
			@Override
			public int compare(SysTradeConsole t1, SysTradeConsole t2) {
				if(null == t1.getTradeGroup()){
					t1.setTradeGroup("");
				}
				if(null == t2.getTradeGroup()){
					t2.setTradeGroup("");
				}
				if(t1.getTradeGroup().toUpperCase().compareTo(t2.getTradeGroup().toUpperCase()) != 0){
					return t1.getTradeGroup().toUpperCase().compareTo(t2.getTradeGroup().toUpperCase());
				}else{
					return t1.getTradeCode().compareTo(t2.getTradeCode());
				}
			}
		});
		PageHandle.startPage(new Page(1,10000));
		Page page = PageHandle.getPlatformPage();
		PageHandle.endPage();
		page.setTotal(tradeList.size());
		int endRow = page.getEndRow() > tradeList.size() ? tradeList.size() : page.getEndRow();
		return tradeList.subList(page.getStartRow(), endRow);
	}

	
	/**
	 * 获取控制器信息
	 * @param tradeCode
	 * @return
	 */
	public SysTradeConsole getTradeConsoleInfo(String tradeCode) {
		SysTradeConsole tcb = stableMap.get(tradeCode).getSysServerConsole();
		return tcb;
	}
	
	/**
	 * 控制器信息修改
	 * @param inBean
	 * @return
	 */
	public int saveServerConsole(SysTradeConsole inBean) {
		logger.debug("保存数据{}",inBean);
		// 同步内存状态
		StableControl stableControl = stableMap.get(inBean.getTradeCode());
		SysTradeConsole sysConsole = stableControl.getSysServerConsole();
		sysTradeConsoleConvertor.copyConsoleBean(sysConsole, inBean);
		stableControl.setSysServerConsole(sysConsole);
		stableControl.synInstance();
		// 同步数据库状态
		return sysServerConsoleDAO.updateByPrimaryKeySelective(sysConsole);
	}

	/**
	 * 控制器信息与数据库表记录的信息同步，服务启动时初始化
	 * stableMap：系统启动时根据Trader初始化到缓存的交易控制器信息
	 * sysServerConsoleDAO：持久化到数据库的交易控制器信息
	 */
	public void loadServerConsole() {
		List<SysTradeConsole> list = sysServerConsoleDAO.selectAll();

		for (Entry<String, StableControl> entry : stableMap.entrySet()) {
			StableControl stableControl = entry.getValue();
			SysTradeConsole tcb = stableControl.getSysServerConsole();
			boolean hasDb = false;
			for (SysTradeConsole sysConsole : list) {
				if (tcb.getTradeCode().equals(sysConsole.getTradeCode())) {
					TradeServiceBean tradeBean = TradeService.getTradeServiceBean(tcb.getTradeCode());
					sysConsole.setTradeName(tcb.getTradeName());
					sysConsole.setImplClass(tcb.getImplClass());
					sysConsole.setTradeGroup(AmsUtils.isNotNull(tradeBean.getTradeGroup())?tradeBean.getTradeGroup():tradeBean.getBeanName());
					sysServerConsoleDAO.updateByPrimaryKeySelective(sysConsole);
					hasDb = true;
				}
			}
			if (!hasDb) {
				TradeServiceBean tradeServiceBean = TradeService.getTradeServiceBean(tcb.getTradeCode());
				tcb.setImplClass(tradeServiceBean.getBeanName() + "." + tradeServiceBean.getMethodName());
				tcb.setTradeGroup(AmsUtils.isNotNull(tradeServiceBean.getTradeGroup())?tradeServiceBean.getTradeGroup():tradeServiceBean.getBeanName());
				sysServerConsoleDAO.insert(sysTradeConsoleConvertor.defaultServerConsole(tcb));
			}
		}
		// 重新查询数据库
		list = sysServerConsoleDAO.selectAll();

		for (SysTradeConsole sysConsole : list) {
			// 如果存在缓存种，则加载数据
			if (stableMap.containsKey(sysConsole.getTradeCode())) {
				StableControl stableControl = stableMap.get(sysConsole.getTradeCode());
				stableControl.setSysServerConsole(sysConsole);
				stableControl.synInstance();
			} else {
				// 如果不存在、删删除数据
				sysServerConsoleDAO.deleteByPrimaryKey(sysConsole.getId());
			}
		}

	}


	/**
	 * 缓存中是控制器信息，由系统启动时根据交易注解Trader初始化
	 * @param trader
	 */
	public static void initStableMap(Trader trader) {
		SysTradeConsole tradeBean = new SysTradeConsole();
		tradeBean.setTradeCode(trader.tradeCode());
		tradeBean.setTradeName(trader.tradeName());
		StableControl stableControl = StableControl.initInstance(trader.tradeCode());
		stableControl.setSysServerConsole(tradeBean);
		stableMap.put(trader.tradeCode(), stableControl);
	}

}
